import { UserOutlined } from '@ant-design/icons';
import { ProCard } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Avatar, Badge, Button, Col, Divider, Empty, Row, Space, Switch, Typography } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import s from './index.less';

const Webrtc: React.FC = () => {
  const localCameraRef = useRef<HTMLVideoElement>(null!);
  const localScreenRef = useRef<HTMLVideoElement>(null!);
  const remoteCameraRef = useRef<HTMLVideoElement>(null!);
  const remoteScreenRef = useRef<HTMLVideoElement>(null!);
  const preViewRef = useRef<HTMLVideoElement>(null!);
  const [screenLoading, setScreenLoading] = useState(false);
  const [cameraLoading, setCameraLoading] = useState(false);
  const [screenVal, setScreenVal] = useState(false);
  const [cameraVal, setCameraVal] = useState(false);
  const [currentRoomId, setCurrentRoomId] = useState(0);
  const [roomCount, setRoomCount] = useState<string[]>([]);
  // const [viewAspect, setViewAspect] = useState('');
  const wsRef = useRef<WebSocket>(null!);
  const pcRef = useRef<RTCPeerConnection>(null!);

  const { Title } = Typography;
  const intl = useIntl();

  //清除pc 和 远程视频流
  function clearPCAndRemote() {
    if (pcRef.current) {
      pcRef.current.close();
      pcRef.current = null!;
    }
    if (preViewRef.current) {
      preViewRef.current.srcObject = null;
    }
    if (remoteScreenRef.current) {
      remoteScreenRef.current.srcObject = null;
    }
    if (remoteCameraRef.current) {
      remoteCameraRef.current.srcObject = null;
    }
  }

  async function createPC(isOffer?: boolean) {
    // 清理旧的连接和媒体流
    const peerConnection = new RTCPeerConnection({
      iceServers: [
        {
          urls: 'turn:shiqiming.cn:3478?transport=tcp',
          username: 'shiqiming',
          credential: '1234',
        },
      ],
    });
    // 确保本地流存在并添加轨道
    const localCameraStream = localCameraRef.current?.srcObject as MediaStream | null;
    if (localCameraStream) {
      localCameraStream.getTracks().forEach((track) => {
        peerConnection.addTrack(track, localCameraStream);
      });
    } else {
      if (!isOffer) {
        peerConnection.addTransceiver('video', { direction: 'recvonly' });
      }
    }

    const localScreenStream = localScreenRef.current?.srcObject as MediaStream | null;
    if (localScreenStream) {
      localScreenStream.getTracks().forEach((track) => {
        peerConnection.addTrack(track, localScreenStream);
      });
    } else {
      if (!isOffer) {
        peerConnection.addTransceiver('video', { direction: 'recvonly' });
      }
    }

    pcRef.current = peerConnection;
    peerConnection.ontrack = (event) => {
      const stream = event.streams[0];
      // 监听track关闭的回调
      if (event.track.kind === 'video') {
        if (remoteCameraRef.current.srcObject) {
          // 已经有摄像头流了，说明这是屏幕共享流
          remoteScreenRef.current.srcObject = stream;
          // console.log('放到了屏幕共享流');
        } else {
          // 没有摄像头流，说明这是摄像头流
          remoteCameraRef.current.srcObject = stream;
          // console.log('放到了摄像头流');
        }
      }
    };

    peerConnection.addEventListener('icecandidate', async function (e) {
      if (e.candidate) {
        const ms = {
          mode: 'ice',
          ice: JSON.stringify(e.candidate),
        };
        wsRef.current.send(JSON.stringify(ms));
      }
    });
    return peerConnection;
  }

  async function call(id: number) {
    clearPCAndRemote();
    const ms = {
      mode: 'door',
      door: String(id),
    };
    setCurrentRoomId(id);
    if (wsRef.current) {
      wsRef.current.send(JSON.stringify(ms));
    }
  }

  function loginOut() {
    clearPCAndRemote();
    setCurrentRoomId(-1);
    const ms = {
      mode: 'loginOut',
    };
    if (wsRef.current) {
      wsRef.current.send(JSON.stringify(ms));
    }
  }

  async function screenHandle(checked: boolean) {
    setScreenLoading(true);
    if (checked) {
      try {
        const screenStream = await navigator.mediaDevices.getDisplayMedia({
          video: true,
        });
        localScreenRef.current.srcObject = screenStream;
        preViewRef.current.srcObject = screenStream;
        setScreenLoading(false);
        setScreenVal(checked);
        call(currentRoomId);
      } catch (error) {
        setScreenLoading(false);
        console.log(
          intl.formatMessage({
            id: 'component.webrtc.screenShareFailed',
            defaultMessage: '共享屏幕失败',
          }),
          error,
        );
      }
    } else {
      setScreenLoading(false);
      setScreenVal(checked);
      if (
        preViewRef.current &&
        preViewRef.current.srcObject &&
        (localScreenRef.current.srcObject as MediaStream).id ===
          (preViewRef.current.srcObject as MediaStream).id
      ) {
        preViewRef.current.srcObject = null;
      }
      // 关闭屏幕共享流
      (localScreenRef.current.srcObject as MediaStream)
        .getTracks()
        .forEach((track) => track.stop());
      localScreenRef.current.srcObject = null;
      call(currentRoomId);
    }
  }
  async function cameraHandle(checked: boolean) {
    setCameraLoading(true);
    if (checked) {
      try {
        const localStream = await navigator.mediaDevices.getUserMedia({
          video: true,
          audio: {
            echoCancellation: true, // 回音消除
            noiseSuppression: true, // 噪声抑制
            autoGainControl: true, // 自动增益控制
          },
        });
        localCameraRef.current.srcObject = localStream;
        preViewRef.current.srcObject = localStream;
        setCameraLoading(false);
        setCameraVal(checked);
        call(currentRoomId);
      } catch (error) {
        setCameraLoading(false);
        console.log(
          intl.formatMessage({
            id: 'component.webrtc.cameraOpenFailed',
            defaultMessage: '打开摄像头失败',
          }),
          error,
        );
      }
    } else {
      setCameraLoading(false);
      setCameraVal(checked);
      if (
        preViewRef.current &&
        preViewRef.current.srcObject &&
        (localCameraRef.current.srcObject as MediaStream).id ===
          (preViewRef.current.srcObject as MediaStream).id
      ) {
        preViewRef.current.srcObject = null;
      }
      // 释放相机流
      (localCameraRef.current.srcObject as MediaStream)
        .getTracks()
        .forEach((track) => track.stop());
      // 使本地流为空，显示默认背影
      localCameraRef.current.srcObject = null;
      call(currentRoomId);
    }
  }

  function getResolution(ref: React.RefObject<HTMLVideoElement>) {
    if (ref.current && ref.current.srcObject) {
      const stream = ref.current.srcObject as MediaStream;
      const videoTrack = stream.getVideoTracks()[0];
      if (videoTrack) {
        const settings = videoTrack.getSettings();
        const aspect = `${settings.width}/${settings.height}`;
        setViewAspect(aspect);
        return aspect;
      }
    }
    return intl.formatMessage({
      id: 'component.webrtc.noResolution',
      defaultMessage: '无',
    });
  }
  function handleView(ref: React.RefObject<HTMLVideoElement>) {
    if (preViewRef.current && ref.current && ref.current.srcObject) {
      preViewRef.current.srcObject = ref.current.srcObject;
      // getResolution(ref);
    }
  }

  useEffect(() => {
    // const ws = new WebSocket('ws://localhost:8088/signal');
    const ws = new WebSocket(WS_SIGNAL);
    wsRef.current = ws;
    ws.onopen = function () {
      if (ws.readyState === 1) {
        call(0);
      }
    };

    ws.onmessage = async function (e) {
      const msg = JSON.parse(e.data);
      if (ws.readyState === WebSocket.CLOSING || ws.readyState === WebSocket.CLOSED) {
        alert(
          intl.formatMessage({
            id: 'component.webrtc.websocketClosing',
            defaultMessage: 'WebSocket is already in CLOSING 状态，无法发送消息。',
          }),
        );
      }
      if (msg.mode === 'ping') {
        const ms = {
          mode: 'pong',
        };
        ws.send(JSON.stringify(ms));
      }
      if (msg.mode === 'offer') {
        const pc = await createPC(true);
        await pcRef.current.setRemoteDescription(JSON.parse(msg.offer));
        const answer = await pc.createAnswer();
        await pc.setLocalDescription(answer);

        const ms = {
          mode: 'answer',
          answer: JSON.stringify(answer),
        };
        ws.send(JSON.stringify(ms));
      }
      if (msg.mode === 'ice') {
        await pcRef.current.addIceCandidate(JSON.parse(msg.ice));
      }
      if (msg.mode === 'answer') {
        await pcRef.current.setRemoteDescription(JSON.parse(msg.answer));
      }
      if (msg.mode === 'message') {
        alert(msg.message);
        setCurrentRoomId(-1);
      }
      if (msg.mode === 'ready') {
        clearPCAndRemote();
        const pc = await createPC();
        const offer = await pc.createOffer();
        await pc.setLocalDescription(offer);
        const ms = {
          mode: 'offer',
          offer: JSON.stringify(offer),
        };
        ws.send(JSON.stringify(ms));
      }
      if (msg.mode === 'allRoomsInfo') {
        const arr = msg.allRoomsInfo;
        if (arr[currentRoomId] === '1') {
          clearPCAndRemote();
        }
        setRoomCount(msg.allRoomsInfo);
      }
    };
    return () => {
      // 关闭WebSocket
      wsRef.current?.close();

      // 关闭PeerConnection
      pcRef.current?.close();

      // 释放所有video流
      [localCameraRef, localScreenRef, remoteCameraRef, remoteScreenRef, preViewRef].forEach(
        (ref) => {
          if (ref.current && ref.current.srcObject) {
            (ref.current.srcObject as MediaStream).getTracks().forEach((track) => track.stop());
            ref.current.srcObject = null;
          }
        },
      );
    };
  }, []);

  return (
    <div style={{ height: '100%' }}>
      <ProCard bordered style={{ height: '100%' }}>
        <Row gutter={[10, 0]} style={{ height: '100%' }}>
          <Col xs={24} md={24} lg={24} xl={18} xxl={20}>
            <ProCard
              bordered
              style={{ height: '100%' }}
              bodyStyle={{
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                padding: '0',
                position: 'relative', // 必须加
                minHeight: '500px',
              }}
            >
              <Empty
                description={intl.formatMessage({
                  id: 'component.webrtc.selectVideoPreview',
                  defaultMessage: '请选择视频预览',
                })}
              ></Empty>
              <video
                autoPlay
                ref={preViewRef}
                style={{
                  position: 'absolute',
                  inset: 0,
                  width: '100%',
                  height: '100%',
                  objectFit: 'contain',
                }}
              ></video>
            </ProCard>
          </Col>
          <Col xs={24} md={24} lg={24} xl={6} xxl={4}>
            <ProCard style={{ minWidth: '230px' }} bordered>
              <Row gutter={[0, 16]} justify="center">
                <Col span={24}>
                  <Space>
                    <Title style={{ marginBottom: '0' }} level={3}>
                      {intl.formatMessage({
                        id: 'component.webrtc.room',
                        defaultMessage: '房间',
                      })}
                    </Title>
                    <Button size="small" onClick={loginOut} type="primary" danger>
                      {intl.formatMessage({
                        id: 'component.webrtc.exit',
                        defaultMessage: '退出',
                      })}
                    </Button>
                  </Space>
                </Col>

                <Col span={24}>
                  <Space>
                    {[0, 1, 2].map((id) => (
                      <Badge count={roomCount[id]} key={id}>
                        <Avatar
                          onClick={() => {
                            call(id);
                          }}
                          style={{
                            backgroundColor: id === currentRoomId ? '#f50' : '#87d068',
                            cursor: 'pointer',
                          }}
                          size="large"
                          icon={<UserOutlined />}
                        />
                      </Badge>
                    ))}
                  </Space>
                </Col>
                <Divider style={{ margin: '0px 0' }} />
                <Col span={24}>
                  <h2>
                    {intl.formatMessage({
                      id: 'component.webrtc.deviceControl',
                      defaultMessage: '设备驱动',
                    })}
                  </h2>
                </Col>
                <Col span={24}>
                  <span>
                    {intl.formatMessage({
                      id: 'component.webrtc.cameraShare',
                      defaultMessage: '摄像共享：',
                    })}
                  </span>
                  <Switch
                    loading={cameraLoading}
                    value={cameraVal}
                    onChange={cameraHandle}
                    defaultChecked
                  />
                </Col>
                <Col style={{ marginTop: '10px' }} span={24}>
                  <span>
                    {intl.formatMessage({
                      id: 'component.webrtc.screenShare',
                      defaultMessage: '录屏共享：',
                    })}
                  </span>
                  <Switch value={screenVal} onChange={screenHandle} loading={screenLoading} />
                </Col>
                <Divider style={{ margin: '0px 0' }} />
                <Col span={24}>
                  <h2>
                    {intl.formatMessage({
                      id: 'component.webrtc.videoPreview',
                      defaultMessage: '视频预览',
                    })}
                  </h2>
                </Col>
                <Col span={24}>
                  <Space wrap>
                    <div className={s.thumbnailBox}>
                      <div className={s['thumbnail-empty']}>
                        {intl.formatMessage({
                          id: 'component.webrtc.localCamera',
                          defaultMessage: '本地相机',
                        })}
                      </div>
                      <video
                        autoPlay
                        onClick={() => {
                          handleView(localCameraRef);
                        }}
                        ref={localCameraRef}
                        className={s.thumbnail}
                      ></video>
                    </div>
                    <div className={s.thumbnailBox}>
                      <div className={s['thumbnail-empty']}>
                        {intl.formatMessage({
                          id: 'component.webrtc.localScreen',
                          defaultMessage: '本地录屏',
                        })}
                      </div>
                      <video
                        autoPlay
                        onClick={() => {
                          handleView(localScreenRef);
                        }}
                        ref={localScreenRef}
                        className={s.thumbnail}
                      ></video>
                    </div>
                    <div className={s.thumbnailBox}>
                      <div className={s['thumbnail-empty']}>
                        {intl.formatMessage({
                          id: 'component.webrtc.remoteCamera',
                          defaultMessage: '对端',
                        })}
                      </div>
                      <video
                        onClick={() => {
                          handleView(remoteCameraRef);
                        }}
                        ref={remoteCameraRef}
                        autoPlay
                        className={s.thumbnail}
                      ></video>
                    </div>
                    <div className={s.thumbnailBox}>
                      <div className={s['thumbnail-empty']}>
                        {intl.formatMessage({
                          id: 'component.webrtc.remoteScreen',
                          defaultMessage: '对端',
                        })}
                      </div>
                      <video
                        onClick={() => {
                          handleView(remoteScreenRef);
                        }}
                        ref={remoteScreenRef}
                        autoPlay
                        className={s.thumbnail}
                      ></video>
                    </div>
                  </Space>
                </Col>
              </Row>
            </ProCard>
          </Col>
        </Row>
      </ProCard>
    </div>
  );
};

export default Webrtc;
